home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
United Public Domain Gold 2
/
United Public Domain Gold 2.iso
/
utilities
/
pu250.dms
/
pu250.adf
/
Graphics
/
Sprites
/
Sprites.doc
< prev
next >
Wrap
Text File
|
1992-04-28
|
26KB
|
871 lines
3 SPRITES
3.1 INTRODUCTION
Sprites are small objects that can be moved around the
display without changing the background. The Amiga has eight
DMA channels which allows us to use 8 Hardware Sprites. The
advantages of using hardware sprites is that they can be moved
around, animated etc without interfering with the main
processor (CPU). They are therefore extremely fast to move,
and also very easy to handle.
Sprites can be used in many situations. If you make a game you
can use the sprites as aliens, missiles, explosion etc. Even
now, when you are reading this, a sprite is used. Intuition's
Pointer is actually a sprite as described in chapter 2 WINDOWS.
3.2 LIMITATIONS
Sprites are wonderful small things but there exist some
limitations:
1. Sprites may only be up to 16 pixels wide. (There is no
limit on how tall they may be.) (Sprites are always using
low-resolution pixels. Even if you have a high-resolution
screen, the sprites will only be in low resolution. This
shows how independent sprites are.)
2. Each sprite can only use three colours + one "transparent"
colour.
3. There are only eight hardware sprites.
These limitations can be avoided:
1. You can place two or more sprites side by side in order
to make the object wider than 16 pixels.
2. You can "connect" two sprites and boast the number of
available colours from 3 to 15 plus one transparent.
3. It is possible to reuse each hardware sprite to "plop" out
several sprites (VSprites) on the display.
3.3 COLOURS
Each sprite may have three different colours plus one
transparent colour. Sprite zero and one will use colour
register 16-19, sprite two and three will use colour register
20-23 and so on:
Sprite Colour Register
-----------------------------------
0 and 1 16 - 19 (16 transparent)
2 and 3 20 - 23 (20 -"- )
4 and 5 24 - 27 (24 -"- )
6 and 7 28 - 31 (28 -"- )
Two important thing to remember:
1. The sprites 0 and 1, 2 and 3, 4 and 5, 6 and 7, use the
same colour registers. If you change colour register 17,
both sprite zero and one will be affected.
2. If you have a low-resolution screen with a depth of 5 (32
colours), the last 16 colours will be shared between the
sprites and the screen. However, if you only use a 16
coloured screen (depth 4) you still use the top sixteen
colour registers for the sprites. That means you can have
a 16 coloured screen, and still use another 16 colours for the
sprites.
Colour register 16, 20, 24 and 28 are "transparent" which
means that the background colour of the screen will shine
through. Those registers can have any kind of colours since
they will not affect the sprites.
3.4 ACCESS HARDWARE SPRITES
If you want to use a hardware sprite you need to:
1. Declare and initialize some sprite graphics data.
2. Declare and initialize a SimpleSprite structure.
3. Call the function GetSprite() with a pointer to your
SimpleSprite structure, plus a request for which sprite
you want, as parameters.
4. Move the sprite around by calling the function MoveSprite()
and animate it by changing the sprite graphics
(ChangeSprite()).
5. Return the sprite to the hardware when you do not need it
anymore, by calling the function FreeSprite().
3.4.1 SPRITE DATA
We have already described how to create your own sprite data
in chapter 2 WINDOWS, but here is a short summary:
[A] The first thing you need to do is to draw on a paper how
the sprite should look like. Remember that the sprite may
only be 16 pixels wide, but any height. (You can of course
put two sprites beside each other if you need a sprite
which is wider than 16 pixels). Remember also that you
may only use three colours/sprite (described above).
Imagine that you have come up with a suggestion like this:
0000000110000000 0: Transparent
0000001111000000 1: Red
0000011111100000 2: Yellow
0000111111110000 3: Green
0001111111111000
0011111111111100
0111111111111110
2222222222222222
2222222222222222
0333333333333330
0033333333333300
0003333333333000
0000333333330000
0000033333300000
0000003333000000
0000000330000000
[B] You now need to translate this into Sprite Data. Each
line of the graphics will be translated into two words
of data. The first word represents the first Bitplane,
and the second word the second Bitplane. The idea is that
if you want colour 0 both Bitplane zero and one should be
0, if you want colour 1 Bitplane zero should be 1 and
Bitplane one 0 and so on:
Colour Bitplane One Bitplane Zero Since
----------------------------------------------------------
0 0 0 Binary 00 = Colour 0
1 0 1 " 01 = " 1
2 1 0 " 10 = " 2
3 1 1 " 11 = " 3
The data for the pointer would then look like this:
Bitplane ZERO Bitplane ONE
0000000110000000 0000000000000000
0000001111000000 0000000000000000
0000011111100000 0000000000000000
0000111111110000 0000000000000000
0001111111111000 0000000000000000
0011111111111100 0000000000000000
0111111111111110 0000000000000000
0000000000000000 1111111111111111
0000000000000000 1111111111111111
0111111111111110 0111111111111110
0011111111111100 0011111111111100
0001111111111000 0001111111111000
0000111111110000 0000111111110000
0000011111100000 0000011111100000
0000001111000000 0000001111000000
0000000110000000 0000000110000000
[C] The last step is to translate the binary numbers to type
UWORD. Group the binary number in four and translate it to
Hexadecimal:
Binary Hexadecimal
-------------------
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 9
1010 = A
1011 = B
1100 = C
1101 = D
1110 = E
1111 = F
The result will look like this:
ONE: TWO:
------------
0180 0000 0000 0001 1000 0000 0000 0000 0000 0000
03C0 0000 0000 0011 1100 0000 0000 0000 0000 0000
07E0 0000 0000 0111 1110 0000 0000 0000 0000 0000
0FF0 0000 0000 1111 1111 0000 0000 0000 0000 0000
1FF8 0000 0001 1111 1111 1000 0000 0000 0000 0000
3FFC 0000 0011 1111 1111 1100 0000 0000 0000 0000
7FFE 0000 0111 1111 1111 1110 0000 0000 0000 0000
0000 FFFF 0000 0000 0000 0000 1111 1111 1111 1111
0000 FFFF 0000 0000 0000 0000 1111 1111 1111 1111
7FFE 7FFE 0111 1111 1111 1110 0111 1111 1111 1110
3FFC 3FFC 0011 1111 1111 1100 0011 1111 1111 1100
1FF8 1FF8 0001 1111 1111 1000 0001 1111 1111 1000
0FF0 0FF0 0000 1111 1111 0000 0000 1111 1111 0000
07E0 07E0 0000 0111 1110 0000 0000 0111 1110 0000
03C0 03C0 0000 0011 1100 0000 0000 0011 1100 0000
0180 0180 0000 0001 1000 0000 0000 0001 1000 0000
[D] Since the Amiga need to store the position of the sprite,
the size etc, you should also declare two empty words at
the top, and to empty words at the bottom of the Sprite
data. These words will be initialized and maintained by
Intuition, so you do not need to bother about them.
A declaration and initialization of the sprite data would
therefore be:
UWORD chip my_sprite_data[36]=
{
0x0000, 0x0000,
0x0180, 0x0000,
0x03C0, 0x0000,
0x07E0, 0x0000,
0x0FF0, 0x0000,
0x1FF8, 0x0000,
0x3FFC, 0x0000,
0x7FFE, 0x0000,
0x0000, 0xFFFF,
0x0000, 0xFFFF,
0x7FFE, 0x7FFE,
0x3FFC, 0x3FFC,
0x1FF8, 0x1FF8,
0x0FF0, 0x0FF0,
0x07E0, 0x07E0,
0x03C0, 0x03C0,
0x0180, 0x0180,
0x0000, 0x0000
};
IMPORTANT! Remember that all image data must as (always!) be
loaded into the Chip memory (the lowest 512k of RAM). If you
use Lattice C V5.00 or higher you can use the keyword chip in
front of the image name. Check your compiler manual.
3.4.2 SIMPLESPRITE STRUCTURE
The SimpleSprite structure look like this:
struct SimpleSprite
{
UWORD *posctldata;
UWORD height;
UWORD x, y;
UWORD num;
};
posctldata: Pointer to an array of UWORDs which is used for
the graphics of the sprite.
height: Height of the sprite (lines). (Hardware Sprites
are always 16 pixels wide.)
x, y: Position on the display relative to the ViewPort/
View (Display).
num: Sprite number (0-7). When you call the GetSprite()
function it will automatically initialize this
field with the reserved sprite number, so set it
to -1 for the moment.
3.4.3 RESERVE A SPRITE
Before you may use a hardware sprite you must have reserved
it. (Since the Amiga is multitasking it can happen that another
program is using the sprite.) You reserve a sprite by calling
the function GetSprite():
Synopsis: sprite_got = GetSprite(my_sprite, sprite_wanted);
sprite_got: (long) GetSprite() returns the number of the
sprite you got (0-7). If it could not get the
desired sprite, it returns -1. Remember to
check if you got the sprite you wanted! (the
SimpleSprite structure's num field will also
be initialized automatically.)
my_sprite: (struct SimpleSprite *) Pointer to your
SimpleSprite structure.
sprite_wanted: (long) The number of the hardware sprite you
want to use (0-7). If it does not matter which
sprite you get you can write -1. (The System
will then give you any free hardware sprite.)
3.4.4 PLAY WITH THE SPRITE
Once you have reserved a sprite you may start to play around
with it. You move the sprite by calling the function
MoveSprite():
Synopsis: MoveSprite( view_port, my_sprite, x, y );
view_port: (struct ViewPort *) Pointer to the ViewPort which
this sprite is connected to, or 0 if the sprite
should be connected to the current View.
my_sprite: (struct SimpleSprite *) Pointer to your SimpleSprite
structure.
x, y: (long) The new position on the display. (Sprites use
low-resolution pixels.)
For example, MoveSprite( 0, &my_sprite, 30, 50 ); moves the
sprite (my_sprite) to position (30, 50). (Relative to the
current View.)
You can also change the image (sprite data) of the sprite in
order to animate it. You simply call the function
ChangeSprite() with a pointer to a new sprite data as a
parameter, and the rest is done for you.
Synopsis: ChangeSprite( view_port, my_sprite, new_data );
view_port: (struct ViewPort *) Pointer to the ViewPort which
this sprite is connected to, or 0 if the sprite is
connected to the current View.
my_sprite: (struct SimpleSprite *) Pointer to your SimpleSprite
structure.
new_data: (short *) Pointer to the new sprite data.
3.4.5 FREE THE SPRITE
When you do not need the sprite any more (when your program
quits for example), you need to free the sprite so another task
can use it if necessary. Important! You must free all sprites
you have allocated, if not no other tasks can use them, and
the only way to free the hardware is then to reset the machine.
You free a sprite by calling the function FreeSprite():
Synopsis: FreeSprite( sprite_got );
sprite_got: (long) The sprite you want to free (0-7).
3.4.6 PROGRAM STRUCTURE
A program using sprites would look something like this:
/* Since we are using sprites we need to include this file: */
#include <graphics/sprite.h>
/* 1. Declare and initialize some sprite graphics data: */
UWORD chip my_sprite_data[36]=
{
0x0000, 0x0000,
0x0180, 0x0000,
0x03C0, 0x0000,
0x07E0, 0x0000,
0x0FF0, 0x0000,
0x1FF8, 0x0000,
0x3FFC, 0x0000,
0x7FFE, 0x0000,
0x0000, 0xFFFF,
0x0000, 0xFFFF,
0x7FFE, 0x7FFE,
0x3FFC, 0x3FFC,
0x1FF8, 0x1FF8,
0x0FF0, 0x0FF0,
0x07E0, 0x07E0,
0x03C0, 0x03C0,
0x0180, 0x0180,
0x0000, 0x0000
};
/* 2. Declare and initialize a SimpleSprite structure: */
struct SimpleSprite my_sprite=
{
my_sprite_data, /* posctldata, pointer to the sprite data. */
16, /* height, 16 lines tall. */
40, 20, /* x, y, position on the screen. */
-1, /* num, this field is automatically */
/* initialized when we call the */
/* GetSprite() function, so we set it */
/* to -1 for the moment. */
};
UWORD chip new_sprite_data[26]=
{
0x0000, 0x0000,
and so on...
main()
{
/* Open the Graphics library etc... */
/* 3. Call the function GetSprite() with a pointer to */
/* your SimpleSprite structure, plus a request for */
/* which sprite you want, as parameters. Try to */
/* reserve sprite number 2: */
if( GetSprite( &my_sprite, 2 ) != 2 )
{
/* ERROR! */
/* Could not reserve sprite number 2. */
}
/* 4. Move the sprite around by calling the function */
/* MoveSprite() and animate it by changing the */
/* sprite graphics by calling the function */
/* ChangeSprite(). */
/* Move the sprite to position (20, 30)
MoveSprite( 0, &my_sprite, 20, 30 );
/* Change the sprite data: */
ChangeSprite( 0, &my_sprite, new_sprite_data );
/* 5. Return the sprite to the hardware when you do not need it */
/* anymore, by calling the function FreeSprite(): */
FreeSprite( my_sprite.num );
/* Close other things etc... */
}
3.5 TECHNIQUES
Since both moving and changing the sprite is done by special
hardware it goes with lightning speed without the main CPU
even knowing about it. If you can you should use the sprites
since the hardware is specialized in handling them. However,
there are, as mentioned before, some limitations which can
cause some problems, but by using some special techniques you
can manage almost anything. Sprites can also be used to create
some interesting special effects, and are perfect to animate.
3.5.1 WIDER SPRITES
If you want a space ship top be 32 pixels wide you can use
two sprites side by side in order to get the desired effects.
Every time you move the ship you call the MoveSprite() function
twice. Since sprites are moved so fast the user will never
realize that the ship is built up of two sprites.
(30,50) (30+16, 50)
*--------------*----------------
| ####|#### |
| # #|# ## |
| #############|############## |
|##############|###############|
| #############|############## |
--------------------------------
Sprite 2 Sprite 3
If you use all eight sprites you can get an image which is
128 pixels wide and any height. I do not think you need a
bigger ship than that.
3.5.2 MORE COLOURS
Each sprite may only use three colours plus transparent.
However, it is possible to connect two sprites and be able
to use 15 colours plus transparent. (Since each sprite use two
Bitplanes, it means that an attached sprite has four Bitplanes
which gives 16 combinations = 15 colours + 1 transparent.)
The sprites may be attached as follows:
1 to 0 (Set the SPRITE_ATTACHED bit in Sprite 1's sprite data)
3 to 2 ( - " - 3 - " - )
5 to 4 ( - " - 5 - " - )
7 to 6 ( - " - 7 - " - )
The even sprites (0, 2, 4 and 6) are called Bottom Sprites,
while the odd sprites (1, 3, 5 and 7) are called Top Sprites.
When you want to use an attached sprite you need to:
1. Declare and initialize two sprite data.
2. Set the Attach bit (on the odd sprite 1, 3, 5 or 7) in
the second word of the sprite data.
3. Once you have reserved both of the sprites, GetSprite(),
they can be moved around. It is important that both sprites
are moved together so the Attach mode works, otherwise they
will become three coloured sprites again.
3.5.2.1 15 COLOURED SPRITE DATA
As you have seen before, the sprite data is built up of two
bitplanes. When we attach two sprites we consequently get four
Bitplanes, and therefore 15 colours plus transparent.
The Bottom Sprite contributes with Bitplane zero and one,
while the Top Sprite contributes with Bitplane two and three.
So if you want the sprite to look like this:
0000000000000000 0: Colour register 16 (Transparent)
1111111111111111 1: - " - 17
2222222222222222 2: - " - 18
3333333333333333 3: - " - 19
4444444444444444 4: - " - 20
5555555555555555 5: - " - 21
6666666666666666 6: - " - 22
7777777777777777 7: - " - 23
8888888888888888 8: - " - 24
9999999999999999 9: - " - 25
AAAAAAAAAAAAAAAA A: - " - 26
BBBBBBBBBBBBBBBB B: - " - 27
CCCCCCCCCCCCCCCC C: - " - 28
DDDDDDDDDDDDDDDD D: - " - 29
EEEEEEEEEEEEEEEE E: - " - 30
FFFFFFFFFFFFFFFF F: - " - 31
The four Bitplanes should be like this:
Bitplane: THREE TWO ONE ZERO
-------------------------------------------------------------------
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 1111111111111111
0000000000000000 0000000000000000 1111111111111111 0000000000000000
0000000000000000 0000000000000000 1111111111111111 1111111111111111
0000000000000000 1111111111111111 0000000000000000 0000000000000000
0000000000000000 1111111111111111 0000000000000000 1111111111111111
0000000000000000 1111111111111111 1111111111111111 0000000000000000
0000000000000000 1111111111111111 1111111111111111 1111111111111111
1111111111111111 0000000000000000 0000000000000000 0000000000000000
1111111111111111 0000000000000000 0000000000000000 1111111111111111
1111111111111111 0000000000000000 1111111111111111 0000000000000000
1111111111111111 0000000000000000 1111111111111111 1111111111111111
1111111111111111 1111111111111111 0000000000000000 0000000000000000
1111111111111111 1111111111111111 0000000000000000 1111111111111111
1111111111111111 1111111111111111 1111111111111111 0000000000000000
1111111111111111 1111111111111111 1111111111111111 1111111111111111
Translated into hexadecimal it would be:
3 2 1 0
-------------------
0000 0000 0000 0000
0000 0000 0000 FFFF
0000 0000 FFFF 0000
0000 0000 FFFF FFFF
0000 FFFF 0000 0000
0000 FFFF 0000 FFFF
0000 FFFF FFFF 0000
0000 FFFF FFFF FFFF
FFFF 0000 0000 0000
FFFF 0000 0000 FFFF
FFFF 0000 FFFF 0000
FFFF 0000 FFFF FFFF
FFFF FFFF 0000 0000
FFFF FFFF 0000 FFFF
FFFF FFFF FFFF 0000
FFFF FFFF FFFF FFFF
Now we only need to put this into the two sprite data. Remember
that the Bottom Sprite (0, 2, 4 or 6) contributes with Bitplanes
zero and one, while the Top Sprites (1, 3, 5 or 7) contributes
with Bitplanes two and three:
/* Sprite Data for the Bottom Sprite: */
UWORD chip bottom_sprite_data[36]=
{
0x0000, 0x0000,
/* Bitplane */
/* ZERO ONE */
0x0000, 0x0000,
0xFFFF, 0x0000,
0x0000, 0xFFFF,
0xFFFF, 0xFFFF,
0x0000, 0x0000,
0xFFFF, 0x0000,
0x0000, 0xFFFF,
0xFFFF, 0xFFFF,
0x0000, 0x0000,
0xFFFF, 0x0000,
0x0000, 0xFFFF,
0xFFFF, 0xFFFF,
0x0000, 0x0000,
0xFFFF, 0x0000,
0x0000, 0xFFFF,
0xFFFF, 0xFFFF,
0x0000, 0x0000
};
/* Sprite Data for the Top Sprite: */
UWORD chip top_sprite_data[36]=
{
0x0000, 0x0000,
/* Bitplane */
/* TWO THREE */
0x0000, 0x0000,
0x0000, 0x0000,
0x0000, 0x0000,
0x0000, 0x0000,
0xFFFF, 0x0000,
0xFFFF, 0x0000,
0xFFFF, 0x0000,
0xFFFF, 0x0000,
0x0000, 0xFFFF,
0x0000, 0xFFFF,
0x0000, 0xFFFF,
0x0000, 0xFFFF,
0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF,
0x0000, 0x0000
};
3.5.2.2 ATTACH SPRITES
To connect two sprites you simply set the SPRITE_ATTACHED
flag in the second word of the sprite data of the Top Sprite.
So if you want to connect sprite 3 with sprite 2, you should
set the SPRITE_ATTACHED flag in sprite 3's sprite data.
top_sprite_data[ 1 ] = SPRITE_ATTACHED;
or
UWORD chip top_sprite_data[36]=
{
0x0000, SPRITE_ATTACHED,
and so on...
3.5.2.3 MOVE ATTACHED SPRITES
Once two sprites are attached you simply reserve them, and you
have got one 15 coloured sprite:
/* Reserve sprite 2 as Bottom Sprite: */
bottom_sprite_got = GetSprite( &my_bottom_sprite, 2 );
if( bottom_sprite_got != 2 )
/* ERROR! */
/* Reserve sprite 3 as Top Sprite: */
top_sprite_got = GetSprite( &my_top_sprite, 3 );
if( top_sprite_got != 3 )
/* ERROR! */
It is important that both of the sprites are moved
simultaneously so the Attach function will work. The nice thing
is that if you move the Bottom sprite, the Top sprite will also
move automatically. If you on the other hand move the Top
sprite only, the Bottom sprite will remain unchanged, and the
special Attach function will no work. (Back to 3 colours.)
If you want to have some fun you can reserve sprite 1 and set
the SPRITE_ATTACHED flag. Since sprite 0 is already used by
Intuition as the pointer, sprite 1 would be attached to the
pointer, and you could have a 15 coloured pointer! (Whenever
Intuition moves the pointer (sprite 0, which is the Bottom
sprite), your sprite (sprite 1, Top Sprite) will move
automatically.) (You can change Intuition's pointer by calling
the function SetPointer. See chapter 2 WINDOWS for more
information.)
3.5.3 LEVELS
Each sprite has its own "level" (priority) which means that
some sprites will move over, and some under other sprites when
they touch each other. The higher sprite number the lower level
(priority). That means that sprite 3 will move over sprite 4,
while sprite 2 will move over sprite 3:
--------
| 7 |
| --------
----| 6 |
| --------
----| 5 |
| --------
----| 4 |
| --------
----| 3 |
| --------
----| 2 |
| --------
----| 1 |
| --------
----| 0 |
| |
--------
This can be used in many ways. For example, if you are writing
a game with a small man jumping into a box, you can use two
sprites. One for the man, and one for the box. The important
thing to remember is that the box must have a lower sprite
number than the man. If you then would place the man at the
same position as the box, the man would appear to go inside
the box:
O
-----
|
^ #######
/ \ #######
Man Box
(Sprite 2) (Sprite 1)
O
-----
|
#######
#######
Man (Sprite 2)
Box (Sprite 1)
3.6 FUNCTIONS
GetSprite()
This function reserves a sprite. You must always reserve a
sprite before you may use it.
Synopsis: spr_got = GetSprite( my_sprite, spr_wanted );
spr_got: (long) GetSprite() returns the number of the
sprite you got (0-7). If it could not get the
desired sprite, it returns -1. Remember to check
if you got the sprite you wanted! (the
SimpleSprite structure's num field will also
be initialized automatically.)
my_sprite: (struct SimpleSprite *) Pointer to your
SimpleSprite structure.
spr_wanted: (long) The number of the hardware sprite you want
to use (0-7). If it does not matter which sprite
you get you can write -1. (The System will then
give you any free hardware sprite)
MoveSprite()
Use this function to move a sprite.
Synopsis: MoveSprite( view_port, my_sprite, x, y );
view_port: (struct ViewPort *) Pointer to the ViewPort which
this sprite is connected to, or 0 if the sprite
is connected to the current View.
my_sprite: (struct SimpleSprite *) Pointer to your
SimpleSprite structure.
x, y: (long) The new position on the display. (Sprites
use low-resolution pixels.)
ChangeSprite()
This function changes the sprite data (image) of a sprite.
Synopsis: ChangeSprite( view_port, my_sprite, new_data );
view_port: (struct ViewPort *) Pointer to the ViewPort which
this sprite is connected to, or 0 if the sprite is
connected to the current View.
my_sprite: (struct SimpleSprite *) Pointer to your
SimpleSprite structure.
new_data: (short *) Pointer to the new sprite data.
FreeSprite()
This function returns an already reserved sprite.
Synopsis: FreeSprite( sprite_got );
sprite_got: (long) The sprite you want to free (0-7).
WaitTOF()
This function waits for the video beam to reach the top of
the display. Can be used if you want to slow down the speed
a bit, and make the animation smoother.
Synopsis: WaitTOF();
3.7 EXAMPLES
Example1
This program shows how to declare and initialize some sprite
data and a SimpleSprite structure. It also shows how to
reserve a sprite (sprite 2), and how to move it around. The
user moves the sprite by pressing the arrow keys.
Example2
This program shows how to declare and initialize some sprite
data and a SimpleSprite structure. It also shows how to
reserve a sprite (sprite 2), and how to move it around. The
user moves the sprite by pressing the arrow keys. In this
example we animate the sprite (6 frames, taken from
the arcade game Miniblast).
Example3
This program shows how to set up a 15 coloured sprite, and
how to move it around.